Skip to content

docs(react): shrink UNGATED_DOCS by one — the react README's 11 blocks compile (#5174 batch 12) - #7910

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-5174-ungated-docs-batch12
Sep 6, 2026
Merged

docs(react): shrink UNGATED_DOCS by one — the react README's 11 blocks compile (#5174 batch 12)#7910
baozhoutao merged 2 commits into
mainfrom
claude/issue-5174-ungated-docs-batch12

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Part of #5174 — batch 12 of the check-doc-snippet-types ungated-docs ledger burn-down. The card stays open; 25 entries remain after this.

packages/react/README.md leaves UNGATED_DOCS and all 11 of its ts/tsx snippets now compile, --strict, against the packages' built dist/*.d.ts. Zero FRAGMENT_MARKER declarations added, zero UNGATED_DOCS entries added — the ledger hunk is git diff --numstat 0 2, removals only.

Ledger and coverage, measured

Both gates — origin/main's copy and this branch's — were imported side by side and evaluated over the same working tree, so the covered-set delta is attributable to the ledger alone and not to a moving tree.

before after
UNGATED_DOCS entries 26 25
covered documents 201 202
covered documents holding a ts/tsx block 99 100
covered blocks 614 625
blocks to compile 456 467
declared fragments 158 158

declared fragments unmoved means every one of the 11 newly covered blocks earned it by compiling; not one was excused with a marker.

Programmatic invariants, printed rather than eyeballed:

LEDGER entry count: 26 -> 25
ADDED entries: []
REMOVED entries: ["packages/react/README.md"]
surviving entries whose REASON TEXT changed: []
COVERED documents: 201 -> 202  STRICTLY GROWS: true
previously-covered docs now UNGATED: []
build filters ADDED [] REMOVED []
scan-set size (documents): 227 -> 227

Gate strictness is unchanged and proved byte for byte: everything from the Fence scanning banner to EOF is identical on origin/main and on this branch — 1117 lines, sha256 91450911e867d61a6f6945d4ea649c894097252d664c792ea69388f230488d59 on both. The gate file is touched only inside the UNGATED_DOCS object literal.

Gate verdict at the final commit c97bd02cb, exit 0:

Scanned 227 document(s): 202 covered (100 of them hold a ts/tsx block), 25 ungated
Covered blocks: 625 — 467 to compile, 158 declared fragment(s).
Syntax phase:   every block parsed, so every one of them reached the semantic phase.
Semantic phase: 467 of 467 block(s) judged, 0 failed.
Every covered documentation snippet compiles against the built types.

What was wrong, and what the repairs are

Seven of the 11 blocks failed. Each is repaired at the document, following the shipped types — no type minted, no export added, no block weakened.

1. useSchemaContext taught an API that does not exist. The example destructured data and updateData. The shipped SchemaRendererContextType declares dataSource, debug, debugFlags and apiFetch, and neither of those two names (packages/react/dist/context/SchemaRendererContext.d.ts). That is the TS2339x2 half of the ledger entry's own reason, and it reproduces exactly. The example now reads what the context actually carries, and record data is pointed at useDataScope, which is the hook that answers it. The prose above it changed with the code.

2. The NON_GRID_ROW_CEILING block did not parse — and a reader copying it hit the same error. Its destructuring statement ended without a semicolon and the next statement opens with <, so ASI does not fire and applyNonGridRowCeiling(result) is parsed as the left side of a relational expression: five syntax errors, TS1005 x3 and TS1109 x2. One semicolon fixes it, with a comment saying why it is load-bearing.

3. The remaining five carried ambient names the page never defined. Those are now declare const against the shipped types, following the pattern packages/data-objectstack/README.md already uses (DataSource and QueryParams from @object-ui/types, ApiFetch from @object-ui/react), plus the two implicitly-any parameter lists given real annotations.

Two claims the prose only asserted are now enforced by the compiler:

  • OBJECT_GRID_BINDING is annotated ElementDataSourceMapping. The paragraph beneath it says a mapping "names ONLY the keys this block reads … a composed value written onto a key the block ignores would be accepted and silently dropped — the defect the binding exists to remove." That is now a compile error rather than a sentence (probe P2).
  • notify()'s severity and displayType literals are checked against the spec unions (probe P1).

The ledger entry's reason text was STALE — reported, not reproduced

The entry read 9 undefined-name diagnostic(s) …; plus TS2339x2 — candidate real defects, un-triaged. What actually reproduced at the branch point was 8 undefined-name plus 4 implicit-any, and — the part the reason does not mention at all — 1 parse failure with 5 diagnostics, in the NON_GRID_ROW_CEILING block that objectui#7210 added after the reason was written. The TS2339x2 half reproduced exactly. A ledger reason is a snapshot of a document that keeps moving; this one had drifted, and the drift is recorded here rather than copied forward.

The labelled-block-statement trap: the negative, stated

Checked per block. Absent from this document, in the strong form: not one of the 11 blocks is a brace-wrapped object literal at all — every block opens with an import statement or a const destructuring. The trap needs a single-key brace-wrapped literal to parse as a labelled block statement and stay green under any spelling; there was no candidate here, single-key or multi-key. So no block in this document was green-under-any-spelling before this change.

Non-vacuity: six planted probes, direction predicted IN WRITING before each run

Predictions were written to a file before the first probe ran. No build artifact sits between a mutation and the thing under test — every mutation edits markdown the gate reads straight from disk, and the dist/ it compiles against is untouched — so no rebuild was needed on either leg, and that is stated rather than assumed. Each leg proved the mutation reached disk (git hash-object differing from the HEAD blob, with an equal hash treated as "this probe did not run" and aborting) and each restore was proved by an empty git diff HEAD plus a blob hash equal to the HEAD blob, never inferred from an exit code. Every probe was run twice — once at f81d879f4 and again at the merged head c97bd02cb — with identical diagnostics.

probe mutation predicted observed
P1 severity: 'success' to 'successs' RED RED, TS2820: Type '"successs"' is not assignable to type 'NotificationSeverityLevel'. Did you mean '"success"'?
P2 mapping key columns: to columnss: RED RED, TS2561: Object literal may only specify known properties, but 'columnss' does not exist in type 'ElementDataSourceMapping'. Did you mean to write 'columns'?
P3 restore the pre-batch const { data, updateData } = useSchemaContext() RED RED, TS2339 x2 — the exact pair the ledger reason recorded
P4 delete the load-bearing semicolon RED, in the syntax phase RED, Syntax phase: 1 block(s) failed to parse and were NOT semantically checked, TS1005 x3 + TS1109 x2
P5 dataSource={adapter} to a string literal GREEN GREEN, exit 0
P6 schema={formSchema} to schema={123} RED RED, TS2322: Type 'number' is not assignable to type 'string | BaseSchema | null | undefined'

Two honest notes on the table. P2's exact code was predicted as TS2353 and observed as TS2561; the direction predicted was RED and the observed diagnostic is the same fact with a spelling suggestion attached. P4's textual before/after counting is degenerate because the post-mutation text is a prefix of the pre-mutation text — the discriminators there are the differing blob hash and the syntax-phase line flipping from "every block parsed" to "1 block(s) failed to parse".

The bound of the green, published rather than left to be found

P5 was predicted GREEN in writing and observed GREEN. SchemaRendererProvider declares dataSource: any in the shipped types, so the SchemaRendererProvider block cannot check what the host injects: replacing the adapter with a bare string raises nothing. That is a real limit of this document's new coverage and it is stated here rather than hidden behind the exit code. It is the same class as objectui#7483 (a props parameter typed bare any makes a wrong prop raise nothing), on a different consumer.

P2 and P6 bound it from the other side: a type without an index signature does catch a wrong key (ElementDataSourceMapping), and a declared member's value type is checked even where the surrounding type is open (SchemaRendererProps.schema refuses number, which its own docblock says is excluded deliberately).

Gates run locally, each quoting its own printed verdict

All at c97bd02cb, exit codes captured by redirect before any pipe, never read after one. git status --porcelain empty at measurement time and after all twelve probe runs.

gate exit its own verdict line
pnpm check:doc-snippets 0 Every covered documentation snippet compiles against the built types.
pnpm check:doc-fences 0 every TypeScript block in 227 document(s) is fenced ts/tsx/typescript, except 80 declared file(s) carrying 89 block(s)
pnpm check:doc-types 0 Every documented component type is registered.
node scripts/check-doc-links.mjs 0 Links are valid across 17 scan roots.
pnpm check:control-bytes 0 OK (scanned 6396 tracked text file(s); skipped 85 binary)
pnpm check:readme-exports 0 426 of them self-imports judged (426 real, 0 wrong-path, 0 fabricated)
pnpm type-check:scripts 0 (tsc -p tsconfig.scripts.json, no output)
node scripts/check-changeset-presence.mjs 0 No source or published contract of a released package changed in this range, so no changeset is owed.
pnpm run lint:root 0 33 problems (0 errors, 33 warnings) — all pre-existing
node scripts/check-governed-queue-guard.mjs --test 0 NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matched.

A manual grep -naP over the C0 control-byte set on both changed files returned no hits, on top of the gate.

lint:root is not a narrowing, three pieces: the population read from eslint's own --format json is 252 files of which 0 are .md/.mdx (so the edited README is outside lint's population entirely); the one changed file inside that population, scripts/check-doc-snippet-types.mjs, reports errorCount 0 warningCount 0; and eslint.config.js sets no project / projectService / tsconfigRootDir, so type-aware linting is off and this diff cannot move the verdict on a file it does not touch.

Vitest, from the repo root, --maxWorkers=2, exit 0: Test Files 13 passed (13) / Tests 545 passed (545). The suite set was derived by git grep -l for the gate's name and for the edited document, and includes scripts/__tests__/check-doc-snippet-types.test.ts — the edited script's own suite, which is owed separately from the doc-gate family. The derived set was identical before and after the merge below.

No changeset — and why, since the dispatch assumed otherwise

scripts/check-changeset-presence.mjs, which AGENTS.md names as the authority, exits 0 with 2 file(s) changed, 0 of them published source of a package the release covers … no changeset is owed: a packages/*/README.md ships inside the package but *.md is subtracted from the files judgement, and scripts/ publishes nothing. Batches 10 and 11 landed the same shape with no changeset (c4f541df9, c39c825d3 — two files each). An empty-frontmatter changeset was written, measured against the gate, and then removed so this PR matches its own precedent and the gate's verdict.

Scope guard

origin/main moved to 84ce0b80d mid-run and was merged, never rebased. It touched four documents in the gate's scan surface (the objectui#7900 guide pages) but no non-test package source, so the built dist/ did not move; every figure above, all six probes included, was nonetheless re-taken after the merge at c97bd02cb, and the dist/index.d.ts of all 26 build-filter packages was confirmed present on disk in this worktree before any gate result was trusted.

Untouched, deliberately: packages/plugin-gantt/README.md and packages/plugin-kanban/README.md (#7302 / PARTIAL_EXCERPTS), packages/plugin-dashboard/README.md (its four untyped example blocks are #7035's), and content/docs/guide/architecture.md / layout.md / schema-rendering.md (PR #7900's, and not ledger entries).

Filed, not fixed here

Two findings were filed unassigned rather than ridden along on a ledger batch:

Draft on purpose, not enqueued, auto-merge not enabled.


Generated by Claude Code

…s compile (#5174 batch 12)

`packages/react/README.md` leaves the `check-doc-snippet-types` coverage
ledger. All 11 of its `ts`/`tsx` snippets are now compiled, `--strict`,
against the packages' built `dist/*.d.ts`: zero `FRAGMENT_MARKER`
declarations added, zero `UNGATED_DOCS` entries added, so the ledger hunk
is 0 additions / 2 deletions.

Seven blocks failed before this change and each is repaired at the
document, never by weakening the gate:

* `useSchemaContext` taught an API that does not exist. It destructured
  `data` and `updateData`; the shipped `SchemaRendererContextType`
  declares `dataSource`, `debug`, `debugFlags` and `apiFetch` and neither
  of those two names. The example now reads what the context carries and
  points record data at `useDataScope`, which is the hook that answers it.
* The `NON_GRID_ROW_CEILING` block did not parse. Its destructuring
  statement ended without a semicolon and the next statement opens with
  `<`, so ASI does not fire and the call is parsed as the left side of a
  relational expression — a reader who copied the block hit the same five
  syntax errors the gate did.
* The remaining five carried ambient names the page never defined. Those
  are now `declare const` against the shipped types, following the
  pattern `packages/data-objectstack/README.md` already uses.

Two claims the prose only asserted are now enforced by the compiler:
`OBJECT_GRID_BINDING` is annotated `ElementDataSourceMapping`, so a key
the block does not read is rejected rather than accepted and dropped, and
`notify()`'s severity and displayType literals are checked against the
spec unions.

Gate strictness is unchanged: the file is touched only inside the
`UNGATED_DOCS` object literal, and everything from the `Fence scanning`
banner to EOF is byte-identical to `origin/main`.

Part of #5174

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013uAaxiwgYDybsTNV9xwa1M
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3187.2 KB 3191.4 KB
Main entry chunk (gzip) 143.4 KB 350 KB
Entry file index-DDlQsBSj.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 510.60KB 116.20KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.98KB 10.98KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.76KB 27.75KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.63KB 8.80KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants